package com.lwt.mvc.config;

import com.google.gson.Gson;
import com.lwt.constant.TongchouConstant;
import com.lwt.exception.AccessForbiddenException;
import com.lwt.exception.LoginAcctAlreadyInUseException;
import com.lwt.exception.LoginFailedException;
import com.lwt.util.ResultEntity;
import com.lwt.util.TongchouUtil;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 封装了公共方法，对普通请求和ajax请求两种情况不同的处理
 * @Author Li Weitong
 * @Date 2021/1/14 18:22
 */
@ControllerAdvice // 表示当前类为一个基于注解的异常处理类
public class TongchouExceptionResolver {

//    @ExceptionHandler(value = NullPointerException.class) // 将一个具体的异常类型和一个方法关联起来
//    public ModelAndView resolveNullPointerException(NullPointerException e, HttpServletRequest req, HttpServletResponse resp) throws IOException { // 实际捕获到的异常类型
//        String viewName = "system-error";
//        return commonResolver(viewName, req, resp,e);
//    }
//    @ExceptionHandler(value = ArithmeticException.class)
//    public ModelAndView resolveArithmeticException(ArithmeticException e, HttpServletRequest req, HttpServletResponse resp) throws IOException { // 实际捕获到的异常类型
//        String viewName = "system-error";
//        return commonResolver(viewName,req,resp,e);
//    }

    /**
     * 如果抛出登录失败的异常，自定义彤筹网的异常处理器，控制发生异常后页面的跳转地地址
     * @param
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(LoginFailedException loginFailedException,HttpServletRequest request,HttpServletResponse response) throws IOException {
        String viewName = "admin-login"; // 登录失败希望 仍 回到登录页面
        return commonResolver(viewName,request, response,loginFailedException);
    }

    /**
     * 抛出拒绝访问异常，自定义彤筹网的异常处理器，通过注解的当时控制发生异常后页面的跳转地址
     * @param req
     * @param resp
     * @param accessForbiddenException
     * @return 跳转到登录页面去登录获取权限
     * @throws IOException
     */
    @ExceptionHandler(value = AccessForbiddenException.class)
    public ModelAndView resolveAccessForbiddenException(HttpServletRequest req, HttpServletResponse resp, AccessForbiddenException accessForbiddenException) throws IOException {
        String viewName = "admin-login";
        return commonResolver(viewName,req,resp,accessForbiddenException);
    }

    /**
     * 抛出用户名已经被使用异常，通过注解配置当登录账号已经存在被使用的异常，并仍跳转到新增页面去显示警告信息
     * @param req
     * @param resp
     * @param loginAcctAlreadyInUseException
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveLoginAcctAlreadyInUserException(HttpServletRequest req, HttpServletResponse resp, LoginAcctAlreadyInUseException loginAcctAlreadyInUseException) throws IOException {
        String viewName = "admin-add";
        return commonResolver(viewName, req, resp,loginAcctAlreadyInUseException);
    }

    /**
     * 抽取出的公共方法
     * @param viewName
     * @param req
     * @param resp
     * @param e
     * @return
     * @throws IOException
     */
    private ModelAndView commonResolver(String viewName,HttpServletRequest req,HttpServletResponse resp,Exception e) throws IOException {
        boolean judgeRequestType = TongchouUtil.judgeRequestType(req);// 判断请求的类型
        if (judgeRequestType){
            ResultEntity<Object> resultEntity = ResultEntity.failed(e.getMessage()); // 创建ResultEntity对象
            String json = new Gson().toJson(resultEntity); // 将ResultEntity对象转换为json字符串
            resp.getWriter().write(json); // 将json字符串作为响应体返回给浏览器
            return null;
        }
        // 如果不是ajax请求
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject(TongchouConstant.ATTR_NAME_EXCEPTION,e);
        modelAndView.setViewName(viewName);
        return modelAndView;
    }
}
